/* Copyright (c) 2016-2020 Enfry Ltd. All Rights Reserved.
 * 
 * This software is the confidential and proprietary information of Enfry. 
 * You shall not disclose such Confidential Information
 * and shall use it only in accordance with the terms of the agreements
 * you entered into with Enfry.
 */
package com.enfry.common.util.array;

import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;

import com.enfry.common.util.Classes;
import com.enfry.common.util.annotation.AnAlias;
import com.enfry.common.util.validate.Validates;

/**
 * 
 * <请简单说明此类用途>
 * 
 * @Title com.enfry.util.Listx
 * @author Penghu
 * @date 2018年1月10日
 */
@AnAlias("Lists")
public class Lists extends Listx {
	/*********************************************/
	// 以下为数组转为列表相关功能
	/*********************************************/

	/**
	 * 清除ArrayList的size之外的无效引用
	 * 
	 * @param list 列表
	 * @return 清除之后的列表
	 */
	public static <T> List<T> trim(List<T> list) {
		if (!(list instanceof ArrayList))
			return list;

		((ArrayList<T>) list).trimToSize();
		return list;
	}

	/**
	 * 数组转列表
	 * 
	 * @param arr 数组对象
	 * @return 结果为列表
	 */
	public static <T> List<T> toList(T[] arr) {
		if (arr == null)
			return new ArrayList<T>(0);

		List<T> list = new ArrayList<T>(arr.length);
		for (T elem : arr)
			list.add(elem);

		return list;
	}

	/**
	 * int[]转列表
	 * 
	 * @param arr 数组
	 * @return 列表
	 */
	public static List<Integer> toList(int[] arr) {
		return toList(Arrays.convert(arr));
	}

	/**
	 * long[]转列表
	 * 
	 * @param arr 数组
	 * @return 列表
	 */
	public static List<Long> toList(long[] arr) {
		return toList(Arrays.convert(arr));
	}

	/**
	 * byte[]转列表
	 * 
	 * @param arr 数组
	 * @return 列表
	 */
	public static List<Byte> toList(byte[] arr) {
		return toList(Arrays.convert(arr));
	}

	/**
	 * short[]转列表
	 * 
	 * @param arr 数组
	 * @return 列表
	 */
	public static List<Short> toList(short[] arr) {
		return toList(Arrays.convert(arr));
	}

	/**
	 * char[]转列表
	 * 
	 * @param arr 数组
	 * @return 列表
	 */
	public static List<Character> toList(char[] arr) {
		return toList(Arrays.convert(arr));
	}

	/**
	 * boolean[]转列表
	 * 
	 * @param arr 数组
	 * @return 列表
	 */
	public static List<Boolean> toList(boolean[] arr) {
		return toList(Arrays.convert(arr));
	}

	/**
	 * float[]转列表
	 * 
	 * @param arr 数组
	 * @return 列表
	 */
	public static List<Float> toList(float[] arr) {
		return toList(Arrays.convert(arr));
	}

	/**
	 * double[]转列表
	 * 
	 * @param arr 数组
	 * @return 列表
	 */
	public static List<Double> toList(double[] arr) {
		return toList(Arrays.convert(arr));
	}

	/*********************************************/
	// 以下为列表和字符串转换相关功能
	/*********************************************/

	/**
	 * 把字符串按逗号分隔转换成字符串数组，注意每个字符串都将trim()操作去除前后空字符串(空格,\r,\n,\t,\b等)
	 * 
	 * @param strs 字符串
	 * @return String[] 转换后的去除前后空格的字符串数组(空格,\r,\n,\t,\b等)
	 */
	public static List<String> toStringList(String strs) {
		return toStringList(strs, ",");
	}

	/**
	 * 把字符串按split分隔转换成字符串数组，注意每个字符串都将trim()操作去除前后空字符串(空格,\r,\n,\t,\b等)
	 * 
	 * @param strs 字符串
	 * @param separator 分隔符
	 * @return String[] 转换后的去除前后空格的字符串数组(空格,\r,\n,\t,\b等)
	 */
	public static List<String> toStringList(String strs, String separator) {
		if (Validates.isEmpty(strs))
			return new ArrayList<String>(0);

		ArrayList<String> strList = new ArrayList<String>();
		String[] array = strs.split(separator);
		for (int i = 0; i < array.length; i++)
			strList.add(array[i].trim());

		strList.trimToSize();
		return strList;
	}

	/**
	 * 把字符串按split分隔转换成整型列表
	 * 
	 * @param strs 字符串
	 * @param separator 分隔符
	 * @return List<Integer> 转换后的整数列表
	 */
	public static List<Integer> toIntList(String strs, String separator) {
		List<String> strList = toStringList(strs, separator);
		return toIntList(strList);
	}

	/**
	 * 把字符串列表传换成整型列表
	 * 
	 * @param strList 字符串列表
	 * @return List<Integer> 转换后的整型列表
	 */
	public static List<Integer> toIntList(List<String> strList) {
		List<Integer> intList = new ArrayList<Integer>(strList.size());
		for (String str : strList)
			intList.add(Integer.parseInt(str.trim()));
		return intList;
	}

	/**
	 * 把字符串按split分隔转换成长整型列表
	 * 
	 * @param strs 字符串
	 * @param separator 分隔符
	 * @return List<Long> 转换后的整数列表
	 */
	public static List<Long> toLongList(String strs, String separator) {
		List<String> strList = toStringList(strs, separator);
		return toLongList(strList);
	}

	/**
	 * 把字符串列表转换成长整型列表
	 * 
	 * @param strList 字符串列表
	 * @return List<Long> 转换后的长整型列表
	 */
	public static List<Long> toLongList(List<String> strList) {
		List<Long> longList = new ArrayList<Long>();
		for (String str : strList)
			longList.add(Long.parseLong(str.trim()));
		return longList;
	}

	/**
	 * 列表转换成分隔符分隔的字符串
	 * 
	 * @param list 对象列表，如List<String>,List<Integer>,List<Long>等
	 * @param separator 分隔符
	 * @return 分隔符分隔的字符串,如 abc,def,pdf
	 */
	public static String toString(List<?> list, String separator) {
		if (list == null || list.size() == 0)
			return "";

		StringBuilder strb = new StringBuilder().append(list.get(0));
		for (int i = 1; i < list.size(); i++) {
			strb.append(separator).append(list.get(i));
		}

		return strb.toString();
	}

	/*********************************************/
	// 以下列表相关工具功能
	/*********************************************/

	/**
	 * 列表位置反转倒序
	 * 
	 * @param oldList 顺序
	 * @return newList 倒序
	 */
	public static <T> ArrayList<T> reverse(ArrayList<T> oldList) {
		ArrayList<T> newList = new ArrayList<T>(oldList.size());
		for (int i = oldList.size() - 1; i >= 0; i--) {
			newList.add(oldList.get(i));
		}

		newList.trimToSize();
		return newList;
	}

	/**
	 * 检查列表中对象的属性中是否匹配指定的值
	 * 
	 * @param list 集合
	 * @param field 对象中的属性名
	 * @param equalValue 指定的值
	 */
	public static boolean contains(Collection<?> list, String field, Object equalValue) {
		if (list == null || list.isEmpty())
			return false;

		if (field == null)
			return list.contains(equalValue);

		// 通过反射机制取属性
		for (Object obj : list) {
			if (obj == null)
				continue;

			Field f = Classes.getFieldDeep(obj.getClass(), field);
			if (f == null)
				continue;

			Object v = Classes.getFieldValue(obj, f);
			if (Validates.isEqual(equalValue, v))
				return true;
		}

		return false;
	}

	/**
	 * 检查列表中对象的属性中是否有匹配指定的值，有则返回该对象
	 * 
	 * @param list 集合
	 * @param field 对象中的属性名
	 * @param equalValue 指定的值
	 * @return 集合中第一个匹配上的对象，如果没有一个匹配则返回null
	 */
	public static <T> T get(Collection<T> list, String field, Object equalValue) {
		if (list == null || list.isEmpty() || equalValue == null)
			return null;

		for (T obj : list) {
			if (obj == null)
				continue;

			if (field == null) {
				if (Validates.isEqual(equalValue, obj))
					return obj;
			} else {
				Field f = Classes.getFieldDeep(obj.getClass(), field);
				if (f == null)
					continue;

				Object v = Classes.getFieldValue(obj, f);
				if (Validates.isEqual(equalValue, v))
					return obj;
			}
		}

		return null;
	}

	/**
	 * 字符串s是否是含有通配符*的pattern能匹配上，如/abc/cde.gif匹配上/a*c/*de.*
	 *
	 * @param s 字符串
	 * @param pattern 含通配符*的字符串，注意该方法中*至少占一个字符
	 * @return 得到匹配的字符串列表
	 */
	public static List<String> getMatchList(String s, String pattern) {
		if (s == null || pattern == null)
			return null;

		int ind = pattern.indexOf("*");
		if (ind == -1) {// 如果匹配字符串不含通配符，则比较两字符串是否相等
			return s.equals(pattern) ? new ArrayList<String>(0) : null;
		}

		ArrayList<String> matchList = new ArrayList<>();
		while (true) {
			if (s.length() <= ind) {// 长度不够没匹配上
				return null;
			}

			if (ind > 0) {// 取出*号前面的内容
				String match = pattern.substring(0, ind);
				if (!s.startsWith(match)) {// 没有匹配上*号前面的内容
					return null;
				}

				// 抹除*号前面的内容，使得*号在第一个位置上
				pattern = pattern.substring(ind);
				s = s.substring(ind);
			}

			// 去除*号
			pattern = pattern.substring(1);
			if (Validates.isEmpty(pattern)) {// *号是最后一个字符表示成功
				matchList.add(s);
				matchList.trimToSize();
				return matchList;
			}

			// 由于*号必须占一个字符，所以s也需要先去除一个字符再比较
			String temp = s.substring(0, 1);
			s = s.substring(1);

			// 下一个*号
			ind = pattern.indexOf("*");
			if (ind == -1) {// 后面没有*号，比较是否后缀匹配成功
				int lastInd = s.lastIndexOf(pattern);
				if (lastInd == -1) {// 没匹配成功
					return null;
				}

				// 成功取通匹值
				String match = temp + s.substring(0, lastInd);
				matchList.add(match);
				matchList.trimToSize();
				return matchList;
			}

			String match = pattern.substring(0, ind);
			int aInd = s.indexOf(match);
			if (aInd == -1)
				return null;

			if (aInd == 0) {// 只匹配到一个字符
				matchList.add(temp);
			} else {// 查到*号对应的内容，放置到通匹符表中，再去除进入下一个*号循环
				matchList.add(temp + s.substring(0, aInd));
				s = s.substring(aInd);
			}
		}
	}
}
